home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / ssh-1.7 / part03 < prev    next >
Encoding:
Text File  |  1993-04-15  |  40.8 KB  |  1,939 lines

  1. Newsgroups: comp.sources.unix
  2. From: Steve Baker (ice@judy.indstate.edu)
  3. Subject: v26i169: ssh - Steve's SHell (a small csh-like shell), V1.7, Part03/04
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: Steve Baker (ice@judy.indstate.edu)
  8. Posting-Number: Volume 26, Issue 169
  9. Archive-Name: ssh-1.7/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 4)."
  18. # Contents:  shcmds.c
  19. # Wrapped by vixie@gw.home.vix.com on Thu Apr 15 22:49:01 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'shcmds.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'shcmds.c'\"
  23. else
  24. echo shar: Extracting \"'shcmds.c'\" \(38412 characters\)
  25. sed "s/^X//" >'shcmds.c' <<'END_OF_FILE'
  26. X/* $Copyright:    $
  27. X * Copyright (c) 1991,1992,1993 by Steve Baker
  28. X * All rights reserved
  29. X *  
  30. X * This software is provided as is without any express or implied
  31. X * warranties, including, without limitation, the implied warranties
  32. X * of merchantability and fitness for a particular purpose.
  33. X */
  34. X#include <errno.h>
  35. X#include <ctype.h>
  36. X#include "shell.h"
  37. X#include "cmds.h"
  38. X
  39. struct Limits {
  40. X  char *resource;
  41. X  long val;
  42. X} limits[6] = {
  43. X  "cpu",RLIMIT_CPU,
  44. X  "filesize",RLIMIT_FSIZE,
  45. X  "datasize",RLIMIT_DATA,
  46. X  "stacksize",RLIMIT_STACK,
  47. X  "coredumpsize",RLIMIT_CORE,
  48. X  "memoryuse",RLIMIT_RSS,
  49. X};
  50. X
  51. char *funcs[] = {
  52. X  0, "Previous history", "Next history", "Move Left", "Move Right",
  53. X  "Delete/Backspace", "Toggle insert/overstrike", "Move to beginning of line",
  54. X  "Delete to the right", "Move to EOL", "Kill to EOL", "Restore line",
  55. X  "Kill line", "Quoted insert", "Find matching history", "Kill to BOL",
  56. X  "Filename completion", "Backward one word", "Forward one word",
  57. X  "Expand line.", "Kill word", "Next character is a control character",
  58. X  "Bell", 0
  59. X};
  60. X
  61. extern char _restricted;
  62. extern char *_home, *_statline, _loginshell, _glob, **_cdpath, _nofork;
  63. extern char ***file, **history, *getenv();
  64. extern char *_kbuf[MAX_GLVL], _kmax[MAX_GLVL];
  65. extern char *exit_val[], *_term[11];
  66. extern int _maxhist, curhist, fptr, _failat;
  67. extern struct custom_keys **keys[MAX_GLVL];
  68. extern struct proc_tab *proc;
  69. extern int max_ent, errno, _pgrp, _string, _status;
  70. extern int _source, err;
  71. extern char path[1025], buf[1025];
  72. extern struct _setvar *setvar, *find_var(), *makenvar();
  73. extern unsigned long SIGMASK;
  74. X
  75. char lif;    /* result of last single line if */
  76. X
  77. char *string(), *UPPER(), *grab(), **evalw();
  78. int setenv();
  79. void unsetenv(), *malloc();
  80. X
  81. int a, b, c, d;
  82. X
  83. execute(cmd,arg,in,inf,out,outf,outa,err,errf,erra,forked)
  84. char cmd,**arg,*inf,*outf,*errf,outa,erra,forked;
  85. int in,out,err;
  86. X{
  87. X  FILE *fin = stdin, *fout = stdout, *ferr = stderr;
  88. X  int pid,n = nargs(arg), rc = 0;
  89. X
  90. X  if (forked) {
  91. X    if (pid = fork()) return pid;
  92. X  }
  93. X  sh_redirect(&in,inf,&out,outf,outa,&err,errf,erra,forked);
  94. X  if (in > 0) fin = fdopen(in,"r");
  95. X  if (out > 1) {
  96. X    if (outa) fout = fdopen(out,"a");
  97. X    else fout = fdopen(out,"w");
  98. X  }
  99. X  if (err > 2 && err != out) {
  100. X    if (erra) ferr = fdopen(err,"a");
  101. X    else ferr = fdopen(err,"w");
  102. X  } else if (err == out) ferr = fout;
  103. X
  104. X  switch(cmd) {
  105. X    case CMD_CD:
  106. X      rc = cd(n,arg,fin,fout,ferr);
  107. X      break;
  108. X    case CMD_HISTORY:
  109. X      rc = hist(n,arg,fin,fout,ferr);
  110. X      break;
  111. X    case CMD_JOBS:
  112. X      rc = jobs(n,arg,fin,fout,ferr);
  113. X      break;
  114. X    case CMD_KEY:
  115. X      rc = key(n,arg,fin,fout,ferr);
  116. X      break;
  117. X    case CMD_ALIAS:
  118. X      rc = ALIAS(n,arg,fin,fout,ferr);
  119. X      break;
  120. X    case CMD_LIMIT:
  121. X      rc = limit(n,arg,fin,fout,ferr);
  122. X      break;
  123. X    case CMD_UNLIMIT:
  124. X      rc = unlimit(n,arg,fin,fout,ferr);
  125. X      break;
  126. X    case CMD_FG:
  127. X      rc = fg(n,arg,fin,fout,ferr);
  128. X      break;
  129. X    case CMD_BG:
  130. X      rc = bg(n,arg,fin,fout,ferr);
  131. X      break;
  132. X    case CMD_STOP:
  133. X      rc = stop(n,arg,fin,fout,ferr);
  134. X      break;
  135. X    case CMD_SOURCE:
  136. X      rc = SOURCE(n,arg,fin,fout,ferr);
  137. X      break;
  138. X    case CMD_SET:
  139. X      rc = SET(n,arg,fin,fout,ferr);
  140. X      break;
  141. X    case CMD_SETENV:
  142. X      rc = SETENV(n,arg,fin,fout,ferr);
  143. X      break;
  144. X    case CMD_UNSETENV:
  145. X      rc = UNSETENV(n,arg,fin,fout,ferr);
  146. X      break;
  147. X    case CMD_UNSET:
  148. X      rc = UNSET(n,arg,fin,fout,ferr);
  149. X      break;
  150. X    case CMD_UNKEY:
  151. X      rc = unkey(n,arg,fin,fout,ferr);
  152. X      break;
  153. X    case CMD_UNALIAS:
  154. X      rc = UNALIAS(n,arg,fin,fout,ferr);
  155. X      break;
  156. X    case CMD_UMASK:
  157. X      rc = UMASK(n,arg,fin,fout,ferr);
  158. X      break;
  159. X    case CMD_EXIT:
  160. X      rc = EXIT(n,arg);
  161. X      break;
  162. X    case CMD_LOGOUT:
  163. X      rc = logout(n,arg,ferr);
  164. X      break;
  165. X    case CMD_VERSION:
  166. X      rc = version(fout);
  167. X      break;
  168. X    case CMD_INPUT:
  169. X      rc = INPUT(n,arg,fin,fout,ferr);
  170. X      break;
  171. X    case CMD_IF:
  172. X      rc = IF(n,arg,ferr);
  173. X      break;
  174. X    case CMD_ELSE:
  175. X      rc = ELSE(n,arg,ferr);
  176. X      break;
  177. X    case CMD_ENDIF:
  178. X      rc = ENDIF(ferr);
  179. X      break;
  180. X    case CMD_LOGIN:
  181. X      rc = login(n,arg,ferr);
  182. X      break;
  183. X    case CMD_SECHO:
  184. X      rc = secho(n,arg,fin,fout,ferr);
  185. X      break;
  186. X    case CMD_WHILE:
  187. X      rc = WHILE(n,arg,ferr);
  188. X      break;
  189. X    case CMD_REPEAT:
  190. X      rc = REPEAT(n,arg,ferr);
  191. X      break;
  192. X    case CMD_BREAK:
  193. X      rc = BREAK(ferr);
  194. X      break;
  195. X    case CMD_CONTINUE:
  196. X      rc = CONTINUE(ferr);
  197. X      break;
  198. X    case CMD_GOTO:
  199. X      rc = GOTO(n,arg,ferr);
  200. X      break;
  201. X    case CMD_FOREACH:
  202. X      rc = FOREACH(n,arg,ferr);
  203. X      break;
  204. X    case CMD_FOR:
  205. X      rc = FOR(n,arg,ferr);
  206. X      break;
  207. X    case CMD_INC:
  208. X      rc = INC(n,arg,ferr);
  209. X      break;
  210. X    case CMD_DEC:
  211. X      rc = DEC(n,arg,ferr);
  212. X      break;
  213. X    case CMD_LABEL:
  214. X      rc = LABEL(n,arg,ferr);
  215. X      break;
  216. X    case CMD_WEND:
  217. X      rc = WEND(ferr);
  218. X      break;
  219. X    case CMD_UNTIL:
  220. X      rc = UNTIL(ferr);
  221. X      break;
  222. X    case CMD_ENDFOR:
  223. X      rc = ENDFOR(ferr);
  224. X      break;
  225. X    case CMD_NEXT:
  226. X      rc = NEXT(ferr);
  227. X      break;
  228. X    case CMD_SWITCH:
  229. X      rc = SWITCH(n,arg,ferr);
  230. X      break;
  231. X    case CMD_ENDSW:
  232. X      rc = ENDSW(ferr);
  233. X      break;
  234. X    case CMD_EVAL:
  235. X      rc = EVAL(n,arg,ferr);
  236. X      break;
  237. X    case CMD_EXEC:
  238. X      rc = EXECUTE(n,arg,ferr);
  239. X      break;
  240. X    case CMD_USAGE:
  241. X      rc = usage(fout,ferr);
  242. X      break;
  243. X    case CMD_INTR:
  244. X      rc = INTR(n,arg,fout,ferr);
  245. X      break;
  246. X    case CMD_TERM:
  247. X      rc = TERM(n,arg,fout,ferr);
  248. X      break;
  249. X    case CMD_PROTECT:
  250. X      rc = PROTECT(n,arg,ferr);
  251. X      break;
  252. X    case CMD_ASSIGN:
  253. X      rc = ASSIGN(n,arg,fout,ferr);
  254. X      break;
  255. X    case CMD_UNASSIGN:
  256. X      rc = UNASSIGN(n,arg,fout,ferr);
  257. X      break;
  258. X    case CMD_SHIFT:
  259. X      rc = SHIFT(n,arg,ferr);
  260. X      break;
  261. X    case CMD_SOPEN:
  262. X      rc = SOPEN(n,arg,ferr);
  263. X      break;
  264. X    case CMD_SCLOSE:
  265. X      rc = SCLOSE(n,arg,ferr);
  266. X      break;
  267. X    case CMD_SREAD:
  268. X      rc = SREAD(n,arg,ferr);
  269. X      break;
  270. X    case CMD_SWRITE:
  271. X      rc = SWRITE(n,arg,ferr);
  272. X      break;
  273. X    case CMD_SSEEK:
  274. X      rc = SSEEK(n,arg,ferr);
  275. X      break;
  276. X  }
  277. X  _status = rc;
  278. X  if (forked) exit(rc);
  279. X  if (in > 0) { fclose(fin); close(in); }
  280. X  if (out > 1) { fclose(fout); close(out); }
  281. X  if (err > 2 && err != out) { fclose(ferr); close(err); }
  282. X  return 0;
  283. X}
  284. X
  285. nargs(arg)
  286. char **arg;
  287. X{
  288. X  int i;
  289. X
  290. X  for(i=0;arg[i];i++);
  291. X  return i;
  292. X}
  293. X
  294. cd(n,arg,in,out,err)
  295. int n;
  296. XFILE *in,*out,*err;
  297. char **arg;
  298. X{
  299. X  if (n > 2) fprintf(err,"cd: too many arguments\n");
  300. X  if (n == 1) {
  301. X    if (!_home) {
  302. X      fprintf(err,"cd: no home directory\n");
  303. X      return 0;
  304. X    }
  305. X    if ((a = chdir(_home)) < 0) c = errno;
  306. X  } else {
  307. X    if ((a = chdir(arg[1])) < 0) {
  308. X      c = errno;
  309. X      if (_cdpath) {
  310. X    for(b=0;_cdpath[b];b++) {
  311. X      sprintf(path,"%s/%s",_cdpath[b],arg[1]);
  312. X      if (chdir(path) < 0) continue;
  313. X      a = 0;
  314. X      break;
  315. X    }
  316. X      }
  317. X    }
  318. X  }
  319. X  if (a < 0) {
  320. X    switch(c) {
  321. X      case ENOTDIR:
  322. X    fprintf(err,"%s: Not a directory\n",arg[1]);
  323. X    break;
  324. X      case ENOENT:
  325. X    fprintf(err,"%s: No such file or directory\n",arg[1]);
  326. X    break;
  327. X      case ELOOP:
  328. X    fprintf(err,"%s: Too many symbolic links.\n",arg[1]);
  329. X    break;
  330. X      default:
  331. X    fprintf(err,"%s: Permission denied.\n",arg[1]);
  332. X    break;
  333. X    }
  334. X    return 1;
  335. X  } else {
  336. X    getwd(path);
  337. X    if (_restricted && strncmp(_home,path,strlen(_home))) {
  338. X      chdir(_home);
  339. X      getwd(path);
  340. X    }
  341. X    makeset("cwd",path);
  342. X  }
  343. X  return 0;
  344. X}
  345. X
  346. limit(n,arg,in,out,err)
  347. int n;
  348. XFILE *in,*out,*err;
  349. char **arg;
  350. X{
  351. X  struct rlimit rlm;
  352. X
  353. X  b = -1;
  354. X  if (n > 1) {
  355. X    for(a=0;a<6;a++)
  356. X      if (!strcmp(arg[1],limits[a].resource)) {
  357. X    b = a;
  358. X    break;
  359. X      }
  360. X  }
  361. X  if (n > 1 && b == -1) {
  362. X    fprintf(err,"limit: undefined limit %s\n",arg[1]);
  363. X    return 1;
  364. X  }
  365. X  if (n < 3) {
  366. X    if (n == 1) {
  367. X      for(a=0;a<6;a++) {
  368. X    getrlimit(limits[a].val,&rlm);
  369. X    if (rlm.rlim_cur == RLIM_INFINITY) fprintf(out,"%-15s unlimited\n",limits[a].resource);
  370. X    else fprintf(out,"%-15s %d K\n",limits[a].resource,rlm.rlim_cur/1024);
  371. X      }
  372. X    } else {
  373. X      getrlimit(limits[b].val,&rlm);
  374. X      if (rlm.rlim_cur == RLIM_INFINITY) fprintf(out,"%-15s unlimited\n",arg[1]);
  375. X      else fprintf(out,"%-15s %d K\n",arg[1],rlm.rlim_cur/1024);
  376. X    }
  377. X  } else if (n == 3) {
  378. X    if (!strcmp(arg[2],"unlimit") || !strcmp(arg[2],"unlimited")) {
  379. X      getrlimit(limits[b].val,&rlm);
  380. X      rlm.rlim_cur = RLIM_INFINITY;
  381. X      setrlimit(limits[b].val,&rlm);
  382. X    } else {
  383. X      if (!isnum(arg[2])) {
  384. X        fprintf(err,"limit: invalid argument - %s\n",arg[2]);
  385. X    return 1;
  386. X      }
  387. X      getrlimit(limits[b].val,&rlm);
  388. X      rlm.rlim_cur = atoi(arg[2]) * 1024;
  389. X      setrlimit(limits[b].val,&rlm);
  390. X    }
  391. X  } else {
  392. X    fprintf(err,"limit: too many arguments\n");
  393. X    return 1;
  394. X  }
  395. X  return 0;
  396. X}
  397. X
  398. unlimit(n,arg,in,out,err)
  399. int n;
  400. XFILE *in,*out,*err;
  401. char **arg;
  402. X{
  403. X  struct rlimit rlm;
  404. X
  405. X  rlm.rlim_cur = RLIM_INFINITY;
  406. X  if (n == 1) {
  407. X    fprintf(err,"unlimit: no limit specified\n");
  408. X    return 1;
  409. X  }
  410. X  if (n > 2) {
  411. X    fprintf(err,"unlimit: too many aguments\n");
  412. X    return 1;
  413. X  }
  414. X  for(a=1;arg[a];a++) {
  415. X    for(b=0;b<6;b++)
  416. X      if (!strcmp(arg[a],limits[b].resource)) {
  417. X    setrlimit(limits[b].val,&rlm);
  418. X    break;
  419. X      }
  420. X    if (b == 6) {
  421. X      fprintf(err,"unlimit: invalid limit\n");
  422. X      return 1;
  423. X    }
  424. X  }
  425. X  return 0;
  426. X}
  427. X
  428. hist(n,arg,in,out,err)
  429. int n;
  430. XFILE *in,*out,*err;
  431. char **arg;
  432. X{
  433. X  char inc = 1, nflg = TRUE;
  434. X
  435. X  c = -1;
  436. X  d = 0;
  437. X  for(a=0;arg[a];a++) {
  438. X    if (arg[a][0] == '-') {
  439. X      switch(arg[a][1]) {
  440. X    case 'r':
  441. X      d = curhist - 1;
  442. X      inc = -1;
  443. X      break;
  444. X    case 'n':
  445. X        nflg = FALSE;
  446. X      break;
  447. X    default:
  448. X      b = atoi(arg[a]+1);
  449. X      if (b > 0) c = b;
  450. X      break;
  451. X      }
  452. X    }
  453. X  }
  454. X  for(a=d;a > -1 && a<curhist && c;a+=inc) {
  455. X    if (nflg) fprintf(out,"%d %s\n",a,history[a]);
  456. X    else fprintf(out,"%s\n",history[a]);
  457. X    if (c != -1) c--;
  458. X  }
  459. X  return 0;
  460. X}
  461. X
  462. key(n,arg,in,out,err)
  463. int n;
  464. XFILE *in,*out,*err;
  465. char **arg;
  466. X{
  467. X  struct custom_keys *key;
  468. X  char lvl=0;
  469. X
  470. X  if (n == 1) {
  471. X    for(b=0;b<MAX_GLVL;b++) {
  472. X      if (!keys[b]) continue;
  473. X      for(a=0;keys[b][a];a++) {
  474. X    fprt(out,keys[b][a]->key);
  475. X    fprintf(out,"\t[%d] ",b);
  476. X    if (keys[b][a]->gold) fprintf(out,"GOLD -> LEVEL %d",keys[b][a]->glvl);
  477. X    else if (keys[b][a]->func) fprintf(out,"Function %2d: %s",keys[b][a]->func,funcs[(keys[b][a]->func)<21?(keys[b][a]->func):21]);
  478. X    else {
  479. X      fputc('"',out);
  480. X      fprt(out,keys[b][a]->cmd);
  481. X      fputc('"',out);
  482. X      if (keys[b][a]->rtn) fprintf(out,"\t[RETURN]");
  483. X      if (keys[b][a]->clr) fprintf(out,"%c[CLEAR]",keys[b][a]->rtn?' ':'\t');
  484. X    }
  485. X    fputc('\n',out);
  486. X      }
  487. X    }
  488. X    return 0;
  489. X  }
  490. X  key = (struct custom_keys *)malloc(sizeof(struct custom_keys));
  491. X  bzero(key,sizeof(struct custom_keys));
  492. X  for(a=1;a<n;a++) {
  493. X    if (arg[a][0] == '-') {
  494. X      switch(arg[a][1]) {
  495. X    case 'r':
  496. X      key->rtn = 1;
  497. X      break;
  498. X    case 'c':
  499. X      key->clr = 1;
  500. X      break;
  501. X    case 'g':
  502. X      key->gold = 1;
  503. X      if (arg[a][2] >= '0' && arg[a][2] <= '4' ) key->glvl = arg[a][2] - 48;
  504. X      else key->glvl = 0;
  505. X      break;
  506. X    case 'l':
  507. X      if (isdigit(arg[a][2]) && arg[a][2] < '5') lvl = arg[a][2] - 48;
  508. X      break;
  509. X    case 'f':
  510. X      key->func = atoi(arg[a]+2);
  511. X      break;
  512. X      }
  513. X    } else break;
  514. X  }
  515. X  if ((a+2 > n && (!key->gold && !key->func)) || (a+1 > n && (key->gold || key->func))) {
  516. X    fprintf(err,"not enough arguments\n");
  517. X    free(key);
  518. X    return 1;
  519. X  }
  520. X  key->key = (char *)strcpy(malloc(strlen(arg[a])+1),arg[a]);
  521. X  a++;
  522. X  if (!key->gold && !key->func) key->cmd = string(arg+a);
  523. X  if (keys[lvl]) {
  524. X    for(a=0;keys[lvl][a];a++) {
  525. X      if (!strcmp(keys[lvl][a]->key,key->key)) {
  526. X    free(keys[lvl][a]->key);
  527. X    if (keys[lvl][a]->cmd) free(keys[lvl][a]->cmd);
  528. X    free(keys[lvl][a]);
  529. X    keys[lvl][a] = key;
  530. X    return 0;
  531. X      }
  532. X    }
  533. X  }
  534. X  if (strlen(key->key) > _kmax[lvl]) _kmax[lvl] = strlen(key->key);
  535. X  a = strlen(_kbuf[lvl]);
  536. X  _kbuf[lvl] = (char *)realloc(_kbuf[lvl],a+2);
  537. X  _kbuf[lvl][a] = key->key[0];
  538. X  _kbuf[lvl][a+1] = 0;
  539. X  if (!keys[lvl]) keys[lvl] = (struct custom_keys **)calloc(2,sizeof(struct custom_keys *));
  540. X  else keys[lvl] = (struct custom_keys **)realloc(keys[lvl], sizeof(struct custom_keys *) * (a+2));
  541. X  keys[lvl][a++] = key;
  542. X  keys[lvl][a] = NULL;
  543. X  return 0;
  544. X}
  545. X
  546. jobs(n,arg,in,out,err)
  547. int n;
  548. char **arg;
  549. XFILE *in,*out,*err;
  550. X{
  551. X  unsigned long mask;
  552. X
  553. X  mask = sigblock(sigmask(SIGCHLD));
  554. X  for(a=0;a<max_ent;a++) {
  555. X    if (proc[a].pid != 0) {
  556. X      if (proc[a].status) {
  557. X    fprintf(out," [%d] (%d) %-30s%s %s\n",a,proc[a].pid,exit_val[proc[a].status],(proc[a].bg?" (background)":""),proc[a].cmd);
  558. X      } else {
  559. X    if (proc[a].bg) fprintf(out," [%d] (%d) %-30s %s\n",a,proc[a].pid,"Running (background)",proc[a].cmd);
  560. X    else fprintf(out," [%d] (%d) %-30s %s\n",a,proc[a].pid,"Running",proc[a].cmd);
  561. X      }
  562. X    }
  563. X  }
  564. X  sigsetmask(mask);
  565. X  return 0;
  566. X}
  567. X
  568. SETENV(n,arg,in,out,err)
  569. int n;
  570. char **arg;
  571. XFILE *in,*out,*err;
  572. X{
  573. X  char *ptr;
  574. X
  575. X  if (n < 2) {
  576. X    fprintf(err,"setenv: not enough arguments\n");
  577. X  } else if (n > 3) {
  578. X    fprintf(err,"setenv: too many arguments\n");
  579. X  } else if (n == 2) {
  580. X    ptr = getenv(arg[1]);
  581. X    if (ptr) {
  582. X      printf("%s=%s\n",arg[1],ptr);
  583. X      free(ptr);
  584. X    }
  585. X  } else {
  586. X    setenv(arg[1],arg[2],1);
  587. X  }
  588. X  return 0;
  589. X}
  590. X
  591. UNSETENV(n,arg,in,out,err)
  592. int n;
  593. char **arg;
  594. XFILE *in,*out,*err;
  595. X{
  596. X  if (n < 2) {
  597. X    fprintf(err,"unsetenv: variable identifier expected.\n");
  598. X  } else if (n > 2) {
  599. X    fprintf(err,"unsetenv: too many arguments.\n");
  600. X  } else {
  601. X    unsetenv(arg[1]);
  602. X  }
  603. X  return 0;
  604. X}
  605. X
  606. fg(n,arg,in,out,err)
  607. int n;
  608. char **arg;
  609. XFILE *in,*out,*err;
  610. X{
  611. X  unsigned long mask;
  612. X
  613. X  if (n > 2) {
  614. X    fprintf(err,"%s: too many args\n",arg[0]);
  615. X    return 1;
  616. X  }
  617. X  if (n == 1) {
  618. X    mask = sigblock(sigmask(SIGCHLD));
  619. X    for(a=0;a<max_ent;a++) {
  620. X      if (proc[a].pid != 0 && (proc[a].bg || proc[a].status)) {
  621. X    if (proc[a].bg) {
  622. X      proc[a].bg = 0;
  623. X      setpgrp(proc[a].pid,proc[a].pid);
  624. X      proc[a].pgrp = proc[a].pid;
  625. X    }
  626. X    if (proc[a].pgrp != _pgrp) tcsetpgrp(TTY,proc[a].pgrp);
  627. X    if (killpg(proc[a].pgrp,SIGCONT) < 0) return 1;
  628. X    proc[a].status = STAT_RUNNING;
  629. X    break;
  630. X      }
  631. X    }
  632. X    sigsetmask(mask);
  633. X    return 0;
  634. X  } else {
  635. X    a = atoi(arg[1]);
  636. X    if (a < 0 || a >= max_ent) {
  637. X      fprintf(err,"%s: No such job: %d\n",a);
  638. X      return 1;
  639. X    }
  640. X    mask = sigblock(sigmask(SIGCHLD));
  641. X    if (proc[a].pid != 0 && (proc[a].bg || proc[a].status)) {
  642. X      if (proc[a].bg) {
  643. X    proc[a].bg = 0;
  644. X    setpgrp(proc[a].pid,proc[a].pid);
  645. X    proc[a].pgrp = proc[a].pid;
  646. X      }
  647. X      if (proc[a].pgrp != _pgrp) tcsetpgrp(TTY,proc[a].pgrp);
  648. X      if (killpg(proc[a].pgrp,SIGCONT) < 0) return 1;
  649. X      proc[a].status = STAT_RUNNING;
  650. X    }
  651. X    sigsetmask(mask);
  652. X  }
  653. X  return 0;
  654. X}
  655. X
  656. bg(n,arg,in,out,err)
  657. int n;
  658. char **arg;
  659. XFILE *in,*out,*err;
  660. X{
  661. X  unsigned long mask;
  662. X
  663. X  if (n > 2) {
  664. X    fprintf(err,"%s: too many args\n",arg[0]);
  665. X    return 1;
  666. X  }
  667. X  if (n == 1) {
  668. X    mask = sigblock(sigmask(SIGCHLD));
  669. X    for(a=0;a<max_ent;a++) {
  670. X      if (proc[a].pid != 0 && !proc[a].bg) {
  671. X    proc[a].bg = 1;
  672. X    setpgrp(proc[a].pid,_pgrp);
  673. X    proc[a].pgrp = _pgrp;
  674. X    tcsetpgrp(TTY,_pgrp);
  675. X    if (killpg(proc[a].pgrp,SIGCONT) < 0) return 1;
  676. X    proc[a].status = STAT_RUNNING;
  677. X    break;
  678. X      }
  679. X    }
  680. X    sigsetmask(mask);
  681. X    return 0;
  682. X  } else {
  683. X    a = atoi(arg[1]);
  684. X    if (a < 0 || a >= max_ent) {
  685. X      fprintf(err,"%s: No such job: %d\n",a);
  686. X      return 1;
  687. X    }
  688. X    mask = sigblock(sigmask(SIGCHLD));
  689. X    if (proc[a].pid != 0 && !proc[a].bg) {
  690. X      proc[a].bg = 1;
  691. X      setpgrp(proc[a].pid,_pgrp);
  692. X      proc[a].pgrp = _pgrp;
  693. X      tcsetpgrp(TTY,_pgrp);
  694. X      if (killpg(proc[a].pgrp,SIGCONT) < 0) return 1;
  695. X      proc[a].status = STAT_RUNNING;
  696. X    }
  697. X    sigsetmask(mask);
  698. X  }
  699. X  return 0;
  700. X}
  701. X
  702. stop(n,arg,in,out,err)
  703. int n;
  704. char **arg;
  705. XFILE *in,*out,*err;
  706. X{
  707. X  unsigned long mask;
  708. X
  709. X  if (n > 2) {
  710. X    fprintf(err,"stop: too many args\n");
  711. X    return 1;
  712. X  }
  713. X  mask = sigblock(sigmask(SIGCHLD));
  714. X  if (n == 1) {
  715. X    for(a=0;a<max_ent;a++) {
  716. X      if (proc[a].pid != 0 && proc[a].bg) {
  717. X    if (killpg(proc[a].pgrp,SIGTSTP) < 0) return 1;
  718. X    break;
  719. X      }
  720. X    }
  721. X  } else {
  722. X    a = atoi(arg[1]);
  723. X    if (proc[a].pid != 0 && proc[a].bg) {
  724. X      if (killpg(proc[a].pgrp,SIGTSTP) < 0) return 1;
  725. X    }
  726. X  }
  727. X  sigsetmask(mask);
  728. X  return 0;
  729. X}
  730. X
  731. SOURCE(n,arg,in,out,err)
  732. int n;
  733. char **arg;
  734. XFILE *in,*out,*err;
  735. X{
  736. X  int i,j,f;
  737. X  char ***tfile;
  738. X
  739. X  if (n < 2) {
  740. X    source(NULL);
  741. X    return 0;
  742. X  }
  743. X  for(i=1;arg[i];i++) {
  744. X    f = fptr;
  745. X    tfile = file;
  746. X    j = source(arg[i]);
  747. X    fptr = f;
  748. X    file = tfile;
  749. X    if (j < 0) {
  750. X      fprintf(err,"source: error opening file %s\n",arg[i]);
  751. X      return 1;
  752. X    }
  753. X  }
  754. X  return 0;
  755. X}
  756. X
  757. unkey(n,arg,in,out,err)
  758. int n;
  759. char **arg;
  760. XFILE *in,*out,*err;
  761. X{
  762. X  c = 0;
  763. X  if (n < 2) {
  764. X    fprintf(stderr,"unkey: macro definition expected.\n");
  765. X    return 1;
  766. X  }
  767. X  for(a=1;arg[a];a++) {
  768. X    if (arg[a][0] == '-') {
  769. X      if (arg[a][1] == 'l') c = atoi(arg[a]+2);
  770. X      else {
  771. X        fprintf(stderr,"unkey: %s invalid argument.\n",arg[a]);
  772. X    return 1;
  773. X      }
  774. X    } else break;
  775. X  }
  776. X  for(b=0;keys[c][b];b++) {
  777. X    if (!strcmp(arg[a],keys[c][b]->key)) {
  778. X      free(keys[c][b]->cmd);
  779. X      free(keys[c][b]->key);
  780. X      free(keys[c][b]);
  781. X      for(;keys[c][b];b++) {
  782. X        keys[c][b] = keys[c][b+1];
  783. X    _kbuf[c][b] = _kbuf[c][b+1];
  784. X      }
  785. X      return 0;
  786. X    }
  787. X  }
  788. X  return 0;
  789. X}
  790. X
  791. UMASK(n,arg,in,out,err)
  792. int n;
  793. char **arg;
  794. XFILE *in, *out, *err;
  795. X{
  796. X  char *ex;
  797. X
  798. X  if (n == 1) {
  799. X    a = umask(0);    
  800. X    fprintf(out,"%03o\n",a);
  801. X    umask(a);
  802. X    return 0;
  803. X  }
  804. X  ex = grab(arg,1,NULL,&a);
  805. X  if (!ex) {
  806. X    fprintf(err,"umask: file protection mask expected.\n");
  807. X    return 1;
  808. X  }
  809. X  a = expr(ex);
  810. X  free(ex);
  811. X  umask(a);
  812. X  return 0;
  813. X}
  814. X
  815. XEXIT(n,arg)
  816. int n;
  817. char **arg;
  818. X{
  819. X  char *ex;
  820. X
  821. X  if (n > 1) {
  822. X    ex = grab(arg,1,NULL,&a);
  823. X    a = expr(ex);
  824. X  } else a = 0;
  825. X  if (_source) {
  826. X    err = ERR_EXIT;
  827. X    return a;
  828. X  }
  829. X  if (_statline) printf("%s%s%s",_term[TS],_term[CE],_term[FS]);
  830. X  exit(a);
  831. X}
  832. X
  833. logout(n,arg,err)
  834. int n;
  835. char **arg;
  836. XFILE *err;
  837. X{
  838. X  static char f = TRUE;
  839. X  unsigned long mask;
  840. X  FILE *fd;
  841. X
  842. X  if (f) {
  843. X    mask = sigblock(sigmask(SIGCHLD));
  844. X    for(a=0;a<max_ent;a++)
  845. X      if (proc[a].pid != 0 && (proc[a].bg || proc[a].status)) {
  846. X    fprintf(err,"You have stopped jobs!\n");
  847. X    f = FALSE;
  848. X    break;
  849. X      }
  850. X    sigsetmask(mask);
  851. X    if (!f) return 1;
  852. X  }
  853. X  
  854. X  if (_loginshell) {
  855. X    for(a=0;a<n;a++) {
  856. X      sprintf(path,"%d",a);
  857. X      makeset(path,arg[a]);
  858. X    }
  859. X    sprintf(path,"%s/%s",_home,HIST_SAVE);
  860. X    b = open(path,O_WRONLY | O_CREAT | O_TRUNC,0600);
  861. X    fd = fdopen(b,"w");
  862. X    fprintf(fd,"%d\n",_maxhist);
  863. X    for(a=0;a < curhist;a++) fprintf(fd,"%s\n",history[a]);
  864. X    fclose(fd);
  865. X    close(b);
  866. X    sprintf(path,"%s/%s",_home,SHELL_EXIT);
  867. X    source(path);
  868. X  }
  869. X  if (_statline) printf("%s%s%s",_term[TS],_term[CE],_term[FS]);
  870. X  exit(0);
  871. X}
  872. X
  873. char *string(wrd)
  874. char **wrd;
  875. X{
  876. X  int i,j;
  877. X  char *str;
  878. X
  879. X  for(i=j=0;wrd[i];i++) j += strlen(wrd[i])+1;
  880. X  str = (char *)malloc(j);
  881. X  strcpy(str,wrd[0]);
  882. X  for(i=1;wrd[i];i++) {
  883. X    strcat(str," ");
  884. X    strcat(str,wrd[i]);
  885. X  }
  886. X  return str;
  887. X}
  888. X
  889. char *UPPER(wrd)
  890. char *wrd;
  891. X{
  892. X  char *tmp;
  893. X
  894. X  tmp = (char *)malloc(strlen(wrd)+1);
  895. X  for(a=0;*wrd;wrd++) tmp[a++] = (islower(*wrd)? toupper(*wrd) : *wrd);
  896. X  tmp[a] = 0;
  897. X  return tmp;
  898. X}
  899. X
  900. fprt(stream,str)
  901. XFILE *stream;
  902. char *str;
  903. X{
  904. X  char c;
  905. X
  906. X  while(*str) {
  907. X    c = *str++ & 127;
  908. X    if (c < 32) {
  909. X      if (_term[SO]) fprintf(stream,"%s%c%s",_term[SO],c+64,_term[SE]);
  910. X      else fprintf(stream,"^%c",c+64);
  911. X    } else if (c == 127) {
  912. X      if (_term[SO]) fprintf(stream,"%s?%s",_term[SO],_term[SE]);
  913. X      else fprintf(stream,"^?");
  914. X    } else fputc(c,stream);
  915. X  }
  916. X}
  917. X
  918. version(out)
  919. XFILE *out;
  920. X{
  921. X  fprintf(out," Ssh V1.7\n Copyright (C) 1991,1992,1993 by Steve Baker and Thomas Moore.\n All rights reserved.\n");
  922. X  return 0;
  923. X}
  924. X
  925. IF(n,arg,ferr)
  926. int n;
  927. char **arg;
  928. XFILE *ferr;
  929. X{
  930. X  long res;
  931. X  int i,nest;
  932. X  int start = fptr, stop = fptr+1, end = fptr+1;
  933. X  char *ex;
  934. X
  935. X  ex = grab(arg,1,"then",&i);
  936. X  if (!ex) {
  937. X    fprintf(ferr,"if: expression expected.\n");
  938. X    return err = 1;
  939. X  }
  940. X  if (!arg[i++]) {
  941. X    fprintf(ferr,"if: keyword 'then' expected.\n");
  942. X    return err = 1;
  943. X  }
  944. X  err = 0;
  945. X  res = expr(ex);
  946. X  free(ex);
  947. X  if (err) return 1;
  948. X
  949. X  if (!_source && !arg[i]) return 1;  
  950. X  nest = 0;
  951. X  if (!arg[i]) {
  952. X    while(file[stop]) {
  953. X      if (!nest && (!strcmp(file[stop][0],"else") || !strcmp(file[stop][0],"endif"))) break;
  954. X      else if (nest && !strcmp(file[stop][0],"endif")) nest--;
  955. X      else if (!strcmp(file[stop][0],"if")) {
  956. X    for(i=1;file[stop][i];i++) {
  957. X      if (!strcmp(file[stop][i],"then"))
  958. X        if (file[stop][i+1]) break;
  959. X        else {
  960. X          nest++;
  961. X          break;
  962. X        }
  963. X    }
  964. X      }
  965. X      stop++;
  966. X    }
  967. X    end = stop;
  968. X    while(file[end]) {
  969. X      if (!nest && !strcmp(file[end][0],"endif")) break;
  970. X      else if (nest && !strcmp(file[end][0],"endif")) nest--;
  971. X      else if (!strcmp(file[end][0],"if")) {
  972. X    for(i=1;file[end][i];i++) {
  973. X      if (!strcmp(file[end][i],"then"))
  974. X        if (file[end][i+1]) break;
  975. X        else {
  976. X          nest++;
  977. X          break;
  978. X        }
  979. X    }
  980. X      }
  981. X      end++;
  982. X    }
  983. X    if (!file[stop] || !file[end]) {
  984. X      fprintf(ferr,"if: unexpected end of file.\n");
  985. X      return err = 1;
  986. X    }
  987. X    if (!res) {
  988. X      start = stop;
  989. X      stop = end;
  990. X    }
  991. X    if (start == end) {
  992. X      fptr = end;
  993. X      return 0;
  994. X    }
  995. X    fptr = start+1;
  996. X    while(fptr < stop) {
  997. X      run(fptr);
  998. X      if (err || badstat(_status)) {
  999. X    fptr = end;
  1000. X    return _status&RET_MASK;
  1001. X      }
  1002. X      fptr++;
  1003. X    }
  1004. X    fptr = end;
  1005. X  } else if (res) {
  1006. X    lif = TRUE;
  1007. X    ex = string(arg+i);
  1008. X    run2(ex);
  1009. X    free(ex);
  1010. X  } else lif = FALSE;
  1011. X  return 0;
  1012. X}
  1013. X
  1014. XELSE(n,arg,err)
  1015. int n;
  1016. char **arg;
  1017. XFILE *err;
  1018. X{
  1019. X  char *cmd;
  1020. X
  1021. X  if (!_source) {
  1022. X    fprintf(err,"else: no previous if-then statement.\n");
  1023. X    return 1;
  1024. X  } else {
  1025. X    if (!fptr || strcmp(file[fptr-1][0],"if")) {
  1026. X      fprintf(err,"else: no previous if-then statement.\n");
  1027. X      return 1;
  1028. X    }
  1029. X    if (n < 2) {
  1030. X      fprintf(err,"else: no command for else condition.\n");
  1031. X      return 1;
  1032. X    }
  1033. X    if (lif) return 0;
  1034. X    cmd = string(arg+1);
  1035. X    run2(cmd);
  1036. X    free(cmd);
  1037. X  }
  1038. X  return 0;
  1039. X}
  1040. X
  1041. XENDIF(err)
  1042. XFILE *err;
  1043. X{
  1044. X  fprintf(err,"else: no previous if-then-else statement.\n");
  1045. X  return 1;
  1046. X}
  1047. X
  1048. INPUT(n,arg,in,out,err)
  1049. int n;
  1050. char **arg;
  1051. XFILE *in, *out, *err;
  1052. X{
  1053. X  char *var = NULL, *prompt = NULL;
  1054. X
  1055. X  c = d = 0;
  1056. X  if (n < 2) {
  1057. X    fprintf(err,"input: not enough arguments\n");
  1058. X    return 1;
  1059. X  }
  1060. X  for(a=1;arg[a];a++) {
  1061. X    if (prompt == arg[a]) continue;
  1062. X    if (arg[a][0] == '-') {
  1063. X      for(b=1;arg[a][b];b++) {
  1064. X    switch(arg[a][b]) {
  1065. X      case 'n':    /* don't replace var if nothing entered. */
  1066. X        c = TRUE;
  1067. X        break;
  1068. X      case 'c':    /* read a single character immediately. */
  1069. X        d = 1;
  1070. X        break;
  1071. X      case 'w':    /* break line up into words. */
  1072. X        d = 2;
  1073. X        break;
  1074. X      case 'e':    /* read single character, echoing it to screen. */
  1075. X        d = 3;
  1076. X        break;
  1077. X      case 'p':    /* Next word is the prompt */
  1078. X        if (arg[a+1]) prompt = arg[a+1];
  1079. X        else {
  1080. X          fprintf(err,"input: no prompt specified.\n");
  1081. X          return 1;
  1082. X        }
  1083. X        break;
  1084. X    }
  1085. X      }
  1086. X    } else if (!var) var = arg[a];
  1087. X    else {
  1088. X      fprintf(err,"input: too many arguments.\n");
  1089. X      return 1;
  1090. X    }
  1091. X  }
  1092. X  if (prompt) fprintf(out,"%s",prompt);
  1093. X  switch (d) {
  1094. X    case 0:
  1095. X    case 2:
  1096. X      fgets(buf,1024,in);
  1097. X      buf[strlen(buf)-1] = 0;
  1098. X      if (buf[0] == 0 && c) return 0;
  1099. X      makeset(var,buf);
  1100. X      return 0;
  1101. X    case 1:
  1102. X    case 3:
  1103. X      noecho();
  1104. X      buf[0] = getchar();
  1105. X      if (d == 3) outch(buf[0]);
  1106. X      buf[1] = 0;
  1107. X      makeset(var,buf);
  1108. X      echo();
  1109. X      return 0;
  1110. X  }
  1111. X  /*NOTREACHED*/
  1112. X}
  1113. X
  1114. login(n,arg,err)
  1115. int n;
  1116. char **arg;
  1117. XFILE *err;
  1118. X{
  1119. X  execv("/bin/login",arg);
  1120. X  fprintf(err,"login: command not found.\n");
  1121. X  return 1;
  1122. X}
  1123. X
  1124. secho(n,arg,in,out,err)
  1125. int n;
  1126. char **arg;
  1127. XFILE *in, *out, *err;
  1128. X{
  1129. X  char *ex;
  1130. X  char x,z;
  1131. X
  1132. X  x = z = b = d = TRUE;
  1133. X  c = FALSE;
  1134. X
  1135. X  for(a=1;arg[a] && x;a++) {
  1136. X    if (z && arg[a][0] == '-' && (!arg[a][1] || !arg[a][2])) {
  1137. X      switch(arg[a][1]) {
  1138. X    case 'n':
  1139. X      b = FALSE;
  1140. X      break;
  1141. X    case 'w':
  1142. X      c = !c;
  1143. X      break;
  1144. X    case 'e':
  1145. X      d = !d;
  1146. X      break;
  1147. X    case 'x':
  1148. X      ex = string(arg+(a+1));
  1149. X      d = expr(ex);
  1150. X      fprintf(out,"%ld",d);
  1151. X      free(ex);
  1152. X      x = c = FALSE;
  1153. X      break;
  1154. X    case 0:
  1155. X      z = FALSE;
  1156. X      break;
  1157. X      }
  1158. X    } else {
  1159. X      if (d) fputs((char *)pline(arg[a],1023,1023),out);
  1160. X      else fputs(arg[a],out);
  1161. X      if (!c && arg[a+1]) fputc(' ',out);
  1162. X      if (c) fputc('\n',out);
  1163. X    }
  1164. X  }
  1165. X  if (b && !c) fputc('\n',out);
  1166. X  return 0;
  1167. X}
  1168. X
  1169. BREAK()
  1170. X{
  1171. X  err = ERR_BREAK;
  1172. X  return 0;
  1173. X}
  1174. X
  1175. CONTINUE()
  1176. X{
  1177. X  err = ERR_CONTINUE;
  1178. X  return 0;
  1179. X}
  1180. X
  1181. WHILE(n,arg,ferr)
  1182. int n;
  1183. char **arg;
  1184. XFILE *ferr;
  1185. X{
  1186. X  int start = fptr+1, end = fptr+1;
  1187. X  char *ex, nest = 0;
  1188. X
  1189. X  if (!_source) return 1;
  1190. X  while(file[end]) {
  1191. X    if (!strcmp(file[end][0],"while")) {
  1192. X      nest++;
  1193. X      end++;
  1194. X      continue;
  1195. X    }
  1196. X    if (!nest && !strcmp(file[end][0],"wend")) break;
  1197. X    if (nest && !strcmp(file[end][0],"wend")) nest--;
  1198. X    end++;
  1199. X  }
  1200. X  if (!file[end]) {
  1201. X    fprintf(ferr,"while: while without matching wend.\n");
  1202. X    return 1;
  1203. X  }
  1204. X  
  1205. X  ex = string(arg+1);
  1206. X  while (expr(ex)) {
  1207. X    fptr = start;
  1208. X    while(fptr < end) {
  1209. X      run(fptr);
  1210. X      if (err == ERR_BREAK) {
  1211. X    fptr = end;
  1212. X    free(ex);
  1213. X        return err = 0;
  1214. X      } else if (err == ERR_CONTINUE) {
  1215. X        err = 0;
  1216. X    break;
  1217. X      }
  1218. X      if (err || badstat(_status)) {
  1219. X    fptr = end;
  1220. X        free(ex);
  1221. X        return _status&RET_MASK;
  1222. X      }
  1223. X      fptr++;
  1224. X    }
  1225. X  }
  1226. X  fptr = end;
  1227. X  free(ex);
  1228. X  return 0;
  1229. X}
  1230. X
  1231. WEND(ferr)
  1232. XFILE *ferr;
  1233. X{
  1234. X  fprintf(ferr,"wend: wend without matching while.\n");
  1235. X  return 1;
  1236. X}
  1237. X
  1238. REPEAT(n,arg,ferr)
  1239. int n;
  1240. char **arg;
  1241. XFILE *ferr;
  1242. X{
  1243. X  int start = fptr+1, end = fptr+1;
  1244. X  char *ex = NULL, nest = 0;
  1245. X
  1246. X  if (!_source) return 1;
  1247. X
  1248. X  while(file[end]) {
  1249. X    if (!strcmp(file[end][0],"repeat")) {
  1250. X      nest++;
  1251. X      end++;
  1252. X      continue;
  1253. X    }
  1254. X    if (!nest && !strcmp(file[end][0],"until")) break;
  1255. X    if (nest && !strcmp(file[end][0],"until")) nest--;
  1256. X    end++;
  1257. X  }
  1258. X  if (!file[end]) {
  1259. X    fprintf(ferr,"repeat: repeat without matching until.\n");
  1260. X    err = 1;
  1261. X    return 1;
  1262. X  }
  1263. X  ex = string(file[end]+1);
  1264. X
  1265. X  do {
  1266. X    fptr = start;
  1267. X    while (fptr < end) {
  1268. X      run(fptr);
  1269. X      if (err == ERR_BREAK) {
  1270. X    fptr = end;
  1271. X    break;
  1272. X      } else if (err == ERR_CONTINUE) {
  1273. X    fptr = end;
  1274. X    err = 0;
  1275. X    break;
  1276. X      }
  1277. X      if (err || badstat(_status)) {
  1278. X    fptr = end;
  1279. X        if (ex) free(ex);
  1280. X        return _status&RET_MASK;
  1281. X      }
  1282. X      fptr++;
  1283. X    }
  1284. X    if (err) break;
  1285. X  } while (!expr(ex));
  1286. X  if (err) err = 0;
  1287. X  free(ex);
  1288. X  return 0;
  1289. X}
  1290. X
  1291. UNTIL(ferr)
  1292. XFILE *ferr;
  1293. X{
  1294. X  fprintf(ferr,"until: until without matching repeat.\n");
  1295. X  return 1;
  1296. X}
  1297. X
  1298. XFOR(n,arg,ferr)
  1299. int n;
  1300. char **arg;
  1301. XFILE *ferr;
  1302. X{
  1303. X  long beg, en, step;
  1304. X  int i,nest = 0, start = fptr+1, end = fptr+1;
  1305. X  char *ex = NULL;
  1306. X  struct _setvar *v;
  1307. X
  1308. X  if (!_source) return 1;
  1309. X
  1310. X  if (arg[1]) v = makenvar(arg[1],0);
  1311. X  else {
  1312. X    fprintf(ferr,"for: missing variable identifier.\n");
  1313. X    return err = 1;
  1314. X  }
  1315. X  if (!arg[2] || arg[2][0] != '=' || arg[2][1] != 0) {
  1316. X    fprintf(ferr,"for: '=' expected.\n");
  1317. X    return err = 1;
  1318. X  }
  1319. X  ex = grab(arg,3,"to", &i);
  1320. X  if (!ex) {
  1321. X    fprintf(ferr,"for: assignment expected.\n");
  1322. X    return err = 1;
  1323. X  }
  1324. X  if (!arg[i]) {
  1325. X    fprintf(ferr,"for: keyword 'to' expected.\n");
  1326. X    return err = 1;
  1327. X  }
  1328. X  beg = expr(ex);
  1329. X  if (err) return 1;
  1330. X  free(ex);
  1331. X  i++;
  1332. X  ex = grab(arg,i,"step",&i);
  1333. X  if (!ex) {
  1334. X    fprintf(ferr,"for: ending value expected.\n");
  1335. X    return err = 1;
  1336. X  }
  1337. X  en = expr(ex);
  1338. X  free(ex);
  1339. X  if (arg[i++]) {
  1340. X    ex = grab(arg,i,NULL,&i);
  1341. X    if (!ex) {
  1342. X      fprintf(ferr,"for: step value expected.\n");
  1343. X      return err = 1;
  1344. X    }
  1345. X    step = expr(ex);
  1346. X    free(ex);
  1347. X  } else step = 1;
  1348. X
  1349. X  while(file[end]) {
  1350. X    if (!nest && !strcmp(file[end][0],"next")) break;
  1351. X    else if (nest && !strcmp(file[end][0],"next")) nest--;
  1352. X    else if (!strcmp(file[end][0],"for")) nest++;
  1353. X    end++;
  1354. X  }
  1355. X  if (!file[end]) {
  1356. X    fprintf(ferr,"for: for without next.\n");
  1357. X    fptr = end-1;
  1358. X    return 1;
  1359. X  }
  1360. X  v->sv.val = beg;
  1361. X
  1362. X  while(1) {
  1363. X    if (step < 0) {
  1364. X      if (v->sv.val < en) break;
  1365. X    } else {
  1366. X      if (v->sv.val > en) break;
  1367. X    }
  1368. X    fptr = start;
  1369. X    while(fptr < end) {
  1370. X      run(fptr);
  1371. X      if (err == ERR_BREAK) {
  1372. X    fptr = end;
  1373. X    return err = 0;
  1374. X      } else if (err == ERR_CONTINUE) {
  1375. X    fptr = end;
  1376. X    err = 0;
  1377. X    break;
  1378. X      }
  1379. X      if (err || badstat(_status)) {
  1380. X    fptr = end;
  1381. X        return _status&RET_MASK;
  1382. X      }
  1383. X      fptr++;
  1384. X    }
  1385. X    if (err == ERR_BREAK) {
  1386. X    }
  1387. X    v->sv.val += step;
  1388. X  }
  1389. X  fptr = end;
  1390. X  return 0;
  1391. X}
  1392. X
  1393. NEXT(ferr)
  1394. XFILE *ferr;
  1395. X{
  1396. X  fprintf(ferr,"next: Next without matching for statement.\n");
  1397. X  return 1;
  1398. X}
  1399. X
  1400. LABEL(n,arg,ferr)
  1401. int n;
  1402. char **arg;
  1403. XFILE *ferr;
  1404. X{
  1405. X  if (n < 2) {
  1406. X    fprintf(ferr,"label: missing label\n");
  1407. X    return 1;
  1408. X  }
  1409. X  if (n > 3) {
  1410. X    fprintf(ferr,"label: too many labels\n");
  1411. X    return 1;
  1412. X  }
  1413. X  return 0;
  1414. X}
  1415. X
  1416. GOTO(n,arg,ferr)
  1417. int n;
  1418. char **arg;
  1419. XFILE *ferr;
  1420. X{
  1421. X  char *lab = NULL;
  1422. X  char dir = 2;
  1423. X  int ptr = fptr;
  1424. X
  1425. X  if (!_source) return 0;
  1426. X  for(a=1;arg[a];a++) {
  1427. X    if (arg[a][0] == '-') {
  1428. X      switch (arg[a][1]) {
  1429. X    case 'f':
  1430. X      dir = 0;
  1431. X      break;
  1432. X    case 'r':
  1433. X      dir = 1;
  1434. X      break;
  1435. X    case 't':
  1436. X      dir = 2;
  1437. X      break;
  1438. X    default:
  1439. X      fprintf(ferr,"goto: invalid switch %s\n",arg[a]);
  1440. X      return 1;
  1441. X      }
  1442. X    } else if (!lab) lab = arg[a];
  1443. X      else {
  1444. X    fprintf(ferr,"goto: illegal argument: %s",arg[a]);
  1445. X    return 1;
  1446. X      }
  1447. X  }
  1448. X  if (dir == 2) dir = ptr = 0;
  1449. X  else if (dir) ptr--;
  1450. X  else ptr++;
  1451. X  if (dir) {
  1452. X    for(; ptr >= 0 ; ptr--) {
  1453. X      if (!strcmp(file[ptr][0],"label")) {
  1454. X        if (!strcmp(file[ptr][1],lab)) {
  1455. X      err = ERR_GOTO;
  1456. X      fptr = ptr;
  1457. X      return 0;
  1458. X    }
  1459. X      }
  1460. X    }
  1461. X  } else {
  1462. X    for(; file[ptr] ; ptr++) {
  1463. X      if (!strcmp(file[ptr][0],"label")) {
  1464. X        if (!strcmp(file[ptr][1],lab)) {
  1465. X      err = ERR_GOTO;
  1466. X      fptr = ptr;
  1467. X      return 0;
  1468. X    }
  1469. X      }
  1470. X    }
  1471. X  }
  1472. X  fprintf(ferr,"goto: label '%s' not found.\n",lab);
  1473. X  return 1;
  1474. X}
  1475. X
  1476. XFOREACH(n,arg,ferr)
  1477. int n;
  1478. char **arg;
  1479. XFILE *ferr;
  1480. X{
  1481. X  int start = fptr+1, end = fptr+1, p = 2;
  1482. X  char *ex = arg[1], nest = 0;
  1483. X
  1484. X  if (!_source) return 1;
  1485. X
  1486. X  while(file[end]) {
  1487. X    if (!strcmp(file[end][0],"foreach")) {
  1488. X      nest++;
  1489. X      end++;
  1490. X      continue;
  1491. X    }
  1492. X    if (!nest && !strcmp(file[end][0],"endfor")) break;
  1493. X    if (nest && !strcmp(file[end][0],"endfor")) nest--;
  1494. X    end++;
  1495. X  }
  1496. X  if (!file[end]) {
  1497. X    fprintf(ferr,"foreach: foreach without matching endfor.\n");
  1498. X    fptr = end-1;
  1499. X    return 1;
  1500. X  }
  1501. X  if (n < 3) {
  1502. X    fprintf(ferr,"foreach: Not enough arguments.\n");
  1503. X    fptr = end;
  1504. X    return 1;
  1505. X  }
  1506. X
  1507. X  while(arg[p]) {
  1508. X    fptr = start;
  1509. X    makeset(ex,arg[p++]);
  1510. X    while (fptr < end) {
  1511. X      run(fptr);
  1512. X      if (err == ERR_BREAK) {
  1513. X    fptr = end;
  1514. X    break;
  1515. X      } else if (err == ERR_CONTINUE) {
  1516. X    fptr = end;
  1517. X    err = 0;
  1518. X    break;
  1519. X      }
  1520. X      if (err || badstat(_status)) {
  1521. X    fptr = end;
  1522. X        return 0;
  1523. X      }
  1524. X      fptr++;
  1525. X    }
  1526. X    if (err) break;
  1527. X  }
  1528. X  fptr = end;
  1529. X  return 0;
  1530. X}
  1531. X
  1532. XENDFOR(ferr)
  1533. XFILE *ferr;
  1534. X{
  1535. X  fprintf(ferr,"endfor: endfor without foreach.\n");
  1536. X  return 1;
  1537. X}
  1538. X
  1539. char *grab(arg,start,hit,pt)
  1540. char **arg;
  1541. char *hit;
  1542. int start,*pt;
  1543. X{
  1544. X  static int i,j,k,p;
  1545. X  static char *ex;
  1546. X
  1547. X  j = 0;
  1548. X  ex = NULL;
  1549. X  if (!hit) {
  1550. X    for(i=start;arg[i];i++) j+= strlen(arg[i]);
  1551. X  } else {
  1552. X    for(i=start;arg[i] && strcmp(arg[i],hit);i++) j+= strlen(arg[i]);
  1553. X  }
  1554. X  if (!j) return NULL;
  1555. X  *pt = i;
  1556. X  ex = (char *)malloc(j+1);
  1557. X  for(p=0,k=start;k<i;k++) {
  1558. X    for(j=0;arg[k][j];j++) ex[p++] = arg[k][j];
  1559. X  }
  1560. X  ex[p] = 0;
  1561. X  return ex;
  1562. X}
  1563. X
  1564. INC(n,arg,ferr)
  1565. int n;
  1566. char **arg;
  1567. XFILE *ferr;
  1568. X{
  1569. X  struct _setvar *s;
  1570. X
  1571. X  if (n < 2) {
  1572. X    fprintf(ferr,"inc: variable expected.\n");
  1573. X    return 1;
  1574. X  }
  1575. X  for(a=1;arg[a];a++) {
  1576. X    s = find_var(arg[a]);
  1577. X    if (!s) makenvar(arg[a],1);
  1578. X    else {
  1579. X      s->sv.val++;
  1580. X    }
  1581. X  }
  1582. X  return 0;
  1583. X}
  1584. X
  1585. DEC(n,arg,ferr)
  1586. int n;
  1587. char **arg;
  1588. XFILE *ferr;
  1589. X{
  1590. X  struct _setvar *s;
  1591. X
  1592. X  if (n < 2) {
  1593. X    fprintf(ferr,"dec: variable expected.\n");
  1594. X    return 1;
  1595. X  }
  1596. X  for(a=1;arg[a];a++) {
  1597. X    s = find_var(arg[a]);
  1598. X    if (!s) makenvar(arg[a],1);
  1599. X    else {
  1600. X      s->sv.val--;
  1601. X    }
  1602. X  }
  1603. X  return 0;
  1604. X}
  1605. X
  1606. XEVAL(n,arg,ferr)
  1607. int n;
  1608. char **arg;
  1609. XFILE *ferr;
  1610. X{
  1611. X  char *ex;
  1612. X
  1613. X  if (n < 2) {
  1614. X    fprintf(ferr,"eval: argument expected.\n");
  1615. X    return 1;
  1616. X  }
  1617. X  ex = string(arg+1);
  1618. X  run2(ex);
  1619. X  free(ex);
  1620. X  return 0;
  1621. X}
  1622. X
  1623. XEXECUTE(n,arg,ferr)
  1624. int n;
  1625. char **arg;
  1626. XFILE *ferr;
  1627. X{
  1628. X  char *ex;
  1629. X
  1630. X  if (n < 2) {
  1631. X    fprintf(ferr,"exec: argument expected.\n");
  1632. X    return 1;
  1633. X  }
  1634. X  ex = string(arg+1);
  1635. X  _nofork = TRUE;
  1636. X  run2(ex);
  1637. X  _nofork = FALSE;
  1638. X  free(ex);
  1639. X  return 1;
  1640. X}
  1641. X
  1642. SWITCH(n,arg,ferr)
  1643. int n;
  1644. char **arg;
  1645. XFILE *ferr;
  1646. X{
  1647. X  char *s = arg[1], l = 0, **etmp, *tmp;
  1648. X  int ptr = fptr+1, start = 0, end = 0, i, j, k;
  1649. X
  1650. X  if (n < 2) {
  1651. X    fprintf(ferr,"switch: string argument expected.\n");
  1652. X    return 1;
  1653. X  }
  1654. X  if (n > 2) {
  1655. X    fprintf(ferr,"switch: Too many arguments.\n");
  1656. X    return 1;
  1657. X  }
  1658. X  for(;file[ptr]; ptr++) {
  1659. X    if (!l && !start && file[ptr][1] && !strcmp("case",file[ptr][0])) {
  1660. X      for(i=1;i<n && start != ptr;i++) {
  1661. X    if (file[ptr][i][0] == '"' || file[ptr][i][0] == '\'') {
  1662. X      j = file[ptr][i][(k=strlen(file[ptr][i]))-1];
  1663. X      file[ptr][i][k-1] = 0;
  1664. X      etmp = evalw(tmp=file[ptr][i]+1);
  1665. X      file[ptr][i][k-1] = j;
  1666. X    } else etmp = evalw(tmp=file[ptr][i]);
  1667. X    for(j=0;etmp[j];j++)
  1668. X      if (patmatch(s,etmp[j])) {
  1669. X        start = ptr;
  1670. X        break;
  1671. X      }
  1672. X    if (tmp != etmp[0])
  1673. X      for(j=0;etmp[j];j++) free(etmp[j]);
  1674. X    free(etmp);
  1675. X      }
  1676. X    } else if (!l && !start && !strcmp("default",file[ptr][0])) {
  1677. X      start = ptr;
  1678. X    } else if (!strcmp("switch",file[ptr][0])) l++;
  1679. X    else if (l && !strcmp("endsw",file[ptr][0])) l--;
  1680. X    else if (!l && !strcmp("endsw",file[ptr][0])) {
  1681. X      end = ptr;
  1682. X      break;
  1683. X    }
  1684. X  }
  1685. X  if (!end) {
  1686. X    fprintf(ferr,"switch: switch without matching endsw.\n");
  1687. X    return 1;
  1688. X  }
  1689. X  if (!start) {
  1690. X    fptr = end;
  1691. X    return 0;
  1692. X  }
  1693. X  fptr = start+1;
  1694. X  while(fptr < end) {
  1695. X    if (!strcmp("case",file[fptr][0]) || !strcmp("default",file[fptr][0])) {
  1696. X      fptr++;
  1697. X      continue;
  1698. X    }
  1699. X    run(fptr);
  1700. X    if (err == ERR_BREAK) {
  1701. X      fptr = end;
  1702. X      err = 0;
  1703. X      return 0;
  1704. X    }
  1705. X    if (err || badstat(_status)) {
  1706. X      fptr = end;
  1707. X      return _status&RET_MASK;
  1708. X    }
  1709. X    fptr++;
  1710. X  }
  1711. X  return 0;
  1712. X}
  1713. X
  1714. XENDSW(ferr)
  1715. XFILE *ferr;
  1716. X{
  1717. X  fprintf(ferr,"endsw: endsw without matching switch.\n");
  1718. X  return 1;
  1719. X}
  1720. X
  1721. usage(fout,ferr)
  1722. XFILE *fout, *ferr;
  1723. X{
  1724. X  static struct rusage ru;
  1725. X
  1726. X  getrusage(RUSAGE_SELF,&ru);
  1727. X  a = ru.ru_utime.tv_sec;
  1728. X  b = a%3600;
  1729. X  c = b%60;
  1730. X  fprintf(fout,"USER time: %02d:%02d:%02d.%06d\t",a/3600,b/60,c,ru.ru_utime.tv_usec);
  1731. X  a = ru.ru_stime.tv_sec;
  1732. X  b = a%3600;
  1733. X  c = b%60;
  1734. X  fprintf(fout,"SYSTEM time: %02d:%02d:%02d.%06d\n",a/3600,b/60,c,ru.ru_stime.tv_usec);
  1735. X  fprintf(fout,"MAX RSS: %dK\tPage Reclaims: %d\t Page faults: %d\n",(ru.ru_maxrss*getpagesize())/1024,ru.ru_minflt,ru.ru_majflt);
  1736. X  fprintf(fout,"SWAPS: %d\tBlocks In: %d\tBlocks Out: %d\tSignals: %d\n",ru.ru_nswap,ru.ru_inblock,ru.ru_oublock,ru.ru_nsignals);
  1737. X  return 0;
  1738. X}
  1739. X
  1740. isnum(w)
  1741. char *w;
  1742. X{
  1743. X  while(*w) if (!isdigit(*w++)) return FALSE;
  1744. X  return TRUE;
  1745. X}
  1746. X
  1747. INTR(n,arg,fout,ferr)
  1748. int n;
  1749. char **arg;
  1750. XFILE *fout, *ferr;
  1751. X{
  1752. X  static char *sigs[] = {
  1753. X    "HUP","INT","QUIT","ILL","TRAP","IOT","EMT","FPE","KILL","BUS","SEGV",
  1754. X    "SYS","PIPE","ALRM","TERM","URG","STOP","TSTP","CONT","CHLD","TTIN",
  1755. X    "TTOU","IO","XCPU","XFSZ","VTALRM","PROF","WINCH","USR1","USR2",0
  1756. X  };
  1757. X
  1758. X  if (n == 1) {
  1759. X    for(a=0;sigs[a];a++)
  1760. X      if (SIGMASK&(1<<a))
  1761. X    fprintf(fout,"%s%s",a?" ":"",sigs[a]);
  1762. X    fputc('\n',fout);
  1763. X    return 0;
  1764. X  }
  1765. X  for(a=1;arg[a];a++) {
  1766. X    if (arg[a][0] == '-' && !arg[a][1]) SIGMASK = 0;
  1767. X    else if (arg[a][0] == '+' && !arg[a][1]) SIGMASK = 0xFFFFFFFF;
  1768. X    else {
  1769. X      for(b=0;sigs[b];b++) {
  1770. X    if (!strcmp(sigs[b],arg[a])) {
  1771. X      SIGMASK ^= (1<<b);
  1772. X      break;
  1773. X    }
  1774. X      }
  1775. X      if (!sigs[b]) {
  1776. X    fprintf(ferr,"intr: %s: invalid argument.\n",arg[a]);
  1777. X    return 1;
  1778. X      }
  1779. X    }
  1780. X  }
  1781. X  return 0;
  1782. X}
  1783. X
  1784. TERM(n,arg,fout,ferr)
  1785. int n;
  1786. char **arg;
  1787. XFILE *fout, *ferr;
  1788. X{
  1789. X  static char *t[12] = {"SO","SE","CE","KS","KE","DC","IC","DS","TC","FS","HS",0};
  1790. X  struct _setvar *VAR;
  1791. X
  1792. X  if (n == 1) {
  1793. X    if ((VAR = find_var("term")) != NULL) fprintf(fout,"term: %s\n",VAR->sv.wrd[0]);
  1794. X    for(a=0;a<10;a++) {
  1795. X      fprintf(fout,"%s\t",t[a]);
  1796. X      if (_term[a]) {
  1797. X        fputc('\042',fout);
  1798. X        fprt(fout,_term[a]);
  1799. X        fputc('\042',fout);
  1800. X      } else fputs("<undefined>",fout);
  1801. X      fputc('\n',fout);
  1802. X    }
  1803. X    fprintf(fout,"HS\t%d\n",_term[HS]);
  1804. X    return 0;
  1805. X  } else {
  1806. X    if (n == 2) {
  1807. X      for(a=0;t[a];a++) {
  1808. X        if (!strcmp(t[a],arg[1])) {
  1809. X      if (a == HS) fprintf(fout,"HS\t%d\n",_term[HS]);
  1810. X      else {
  1811. X        fprintf(fout,"%s\t",t[a]);
  1812. X        if (_term[a]) {
  1813. X          fputc('\042',fout);
  1814. X          fprt(fout,_term[a]);
  1815. X          fputc('\042',fout);
  1816. X        } else fputs("<undefined>",fout);
  1817. X        fputc('\n',fout);
  1818. X      }
  1819. X      return 0;
  1820. X    }
  1821. X      }
  1822. X      fprintf(ferr,"term: %s not found.\n",arg[1]);
  1823. X      return 1;
  1824. X    } else {
  1825. X      for(a=0;t[a];a++) {
  1826. X        if (!strcmp(t[a],arg[1])) {
  1827. X      if (a == HS) _term[HS] = (char *)atoi(arg[2]);
  1828. X      else {
  1829. X        free(_term[a]);
  1830. X        _term[a] = string(arg+2);
  1831. X        if (!strlen(_term[a])) {
  1832. X          free(_term[a]);
  1833. X          _term[a] = NULL;
  1834. X        }
  1835. X      }
  1836. X      return 0;
  1837. X    }
  1838. X      }
  1839. X      fprintf(ferr,"term: %s not found.\n",arg[1]);
  1840. X      return 1;
  1841. X    }
  1842. X  }
  1843. X}
  1844. X
  1845. PROTECT(n,arg,ferr)
  1846. int n;
  1847. char **arg;
  1848. XFILE *ferr;
  1849. X{
  1850. X  struct _setvar *VAR;
  1851. X
  1852. X  if (n < 2) {
  1853. X    fprintf(ferr,"protect: missing argument.\n");
  1854. X    return 1;
  1855. X  }
  1856. X  if ((VAR = find_var(arg[1])) == NULL) {
  1857. X    fprintf(ferr,"protect: %s not found.\n",arg[1]);
  1858. X    return 1;
  1859. X  }
  1860. X  VAR->protect = 1;
  1861. X  return 0;
  1862. X}
  1863. X
  1864. X#ifdef NOSETENV
  1865. extern char **environ;
  1866. extern int errno;
  1867. X
  1868. int setenv(name,value,overwrite)
  1869. char *name, *value;
  1870. int overwrite;
  1871. X{
  1872. X  int i, l = strlen(name);
  1873. X  char **tmp, **se = environ;
  1874. X
  1875. X  if (name[l-1] == '=') l--;
  1876. X  for(i=0;environ[i];i++) {
  1877. X    if (!strncmp(name,environ[i],l) && environ[i][l] == '=') {
  1878. X      if (overwrite) {
  1879. X        free(environ[i]);
  1880. X    break;
  1881. X      }
  1882. X      return 0;
  1883. X    }
  1884. X  }
  1885. X  if (!environ[i]) {
  1886. X    if ((environ = (char **)realloc(environ,sizeof(char *)*(i+2))) == NULL) {
  1887. X      if (errno == EINVAL) {
  1888. X    if ((tmp = (char **)malloc(sizeof(char *) * (i+2))) == NULL) return -1;
  1889. X    for(i=0;se[i];i++) tmp[i] = se[i];
  1890. X    environ = tmp;
  1891. X      } else return -1;
  1892. X    }
  1893. X    environ[i+1] = NULL;
  1894. X  }
  1895. X  if ((environ[i] = (char *)malloc(l+strlen(value)+2)) == NULL) return -1;
  1896. X  sprintf(environ[i],"%.*s=%s",l,name,value[0]=='='?value+1:value);
  1897. X  return 0;
  1898. X}
  1899. X
  1900. void unsetenv(name)
  1901. char *name;
  1902. X{
  1903. X  int i = 0, j, f = 0, l = strlen(name);
  1904. X
  1905. X  if (name[l-1] == '=') l--;
  1906. X  while(environ[i]) {
  1907. X    if (!strncmp(name,environ[i],l) && environ[i][l] == '=') {
  1908. X      f = 1;
  1909. X      free(environ[i]);
  1910. X      for(j=i;environ[j];j++) environ[j] = environ[j+1];
  1911. X    } else i++;
  1912. X  }
  1913. X/*  if (f) environ = (char **)realloc(environ,sizeof(char *) * i+1); */
  1914. X}
  1915. X#endif
  1916. END_OF_FILE
  1917. if test 38412 -ne `wc -c <'shcmds.c'`; then
  1918.     echo shar: \"'shcmds.c'\" unpacked with wrong size!
  1919. fi
  1920. # end of 'shcmds.c'
  1921. fi
  1922. echo shar: End of archive 3 \(of 4\).
  1923. cp /dev/null ark3isdone
  1924. MISSING=""
  1925. for I in 1 2 3 4 ; do
  1926.     if test ! -f ark${I}isdone ; then
  1927.     MISSING="${MISSING} ${I}"
  1928.     fi
  1929. done
  1930. if test "${MISSING}" = "" ; then
  1931.     echo You have unpacked all 4 archives.
  1932.     rm -f ark[1-9]isdone
  1933. else
  1934.     echo You still need to unpack the following archives:
  1935.     echo "        " ${MISSING}
  1936. fi
  1937. ##  End of shell archive.
  1938. exit 0
  1939.